package com.feng.common.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.feng.common.utils.AssertUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.function.Consumer;

/**
 * WEB统一返回类
 *
 * @author: Jack.Cheng
 * @date: 2021/6/99 17:06
 */
@JsonIgnoreProperties(ignoreUnknown = true)
@ToString
@Getter
@Setter
@Builder
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {

    private static final long serialVersionUID = -4781082011605001370L;

    public final static String APP_RETURN_SUCCESS = "0";
    public final static String APP_RETURN_FAILED = "1000";
    public final static String APP_MSG_RETURN_SUCCESS = "success";

    /**
     * 状态码
     * <p>
     * 状态码要求全局唯一,方便问题排查
     * </p>
     */
    private String code;
    private String msg;
    private String uri;
    private T data;
    @Builder.Default
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private LocalDateTime timestamp = LocalDateTime.now();

    public static <T> Result<T> ok() {
        return Result.ok(null);
    }

    public static <T> Result<T> ok(T data) {
        return Result.<T>builder().code(APP_RETURN_SUCCESS)
                .data(data)
                .msg(APP_MSG_RETURN_SUCCESS)
                .build();
    }

    public static <T> Result<T> ok(T data, String uri) {
        return Result.<T>builder().code(APP_RETURN_SUCCESS)
                .data(data)
                .uri(uri)
                .msg(APP_MSG_RETURN_SUCCESS)
                .build();
    }

    public static <T> Result<T> fail(String code, String reason) {
        AssertUtils.hasText(code, "code must not be blank");
        return Result.<T>builder().code(code)
                .msg(reason)
                .build();
    }

    public static <T> Result<T> fail(String reason) {
        return Result.<T>builder().code(APP_RETURN_FAILED)
                .msg(reason)
                .build();
    }

    @JsonIgnore
    public boolean isOk() {
        return APP_RETURN_SUCCESS.equals(this.code);
    }

    @JsonIgnore
    public boolean isFail() {
        return !isOk();
    }

    public void ifOk(Consumer<? super T> action) {
        if (isOk() && this.data != null) {
            action.accept(this.data);
        }
    }
}
